package.cpath = "luaclib/?.so;3rd/lua-cjson/?.so;shao/?.lua;"
local skynet = require "skynet"
local queue = require "skynet.queue"
local packdeal = require "packdeal"
local send_package = packdeal.send_package
local unpack_package = packdeal.unpack_package

require "config_redis"
local NetCmd = require "common/NetCmd"
require "common/schema"
require "common/user_t"
local json = require "cjson"
json.encode_sparse_array(true)
local MAIL = require "module/mail"

local httpc = require "http.httpc"


CMD = {}
POST = {}
REQUEST = {}

local watch_dog
local gate_fd
local client_fd = nil
local room_id = nil
local room_fd = nil
local user = nil
local exit = false
local time_out_stop_room_agent = 0
local cs = queue()

local is_flag_room = 0

-- 用户请求队列，现在是REQUEST的函数都用同一个队列
function make_queue(user, json_data, func)
    local function closure()
        func(user, json_data)
    end
    cs(closure)
end

local function destory(no_send_out)
    -- if room_fd ~= nil then
    --     skynet.call(room_fd, "lua", "out_line", user.uid, 1)
    -- end
    -- if no_send_out == nil then
    skynet.send(watch_dog, "lua", "destory", user.account, user.uid)
    -- end
    skynet.exit()
end

-- 服务器直接踢掉玩家
function CMD.kick(address)
    skynet.call(gate_fd, "lua", "kick", client_fd)
end


-- 玩家断线处理
function CMD.close(address, no_send_out)
    -- if room_id ~= nil and room_id > 0 then
    --     local hall_name = skynet.call("MG_SAVE", "lua", "hall_name_hget", room_id)
    --     if hall_name ~= nil then
    --         room_fd = skynet.call(hall_name, "lua", "get_rooms", room_id)
    --         if room_fd ~= nil then
    --             skynet.call(room_fd, "lua", "out_line", user.uid, 1)
    --         end
    --     end
    -- end
    destory(no_send_out)
end

-- 玩家断线处理
function CMD.heart()
    if room_id ~= nil and room_id > 0 then
        local hall_name = skynet.call("MG_SAVE", "lua", "hall_name_hget", room_id)
        room_fd = skynet.call(hall_name, "lua", "get_rooms", room_id)
        if room_fd ~= nil then
            skynet.call(room_fd, "lua", "out_line", user.uid, 1)
        end
    end
    destory()
end

function CMD.heart_inline(address)
    if room_fd and room_fd > 0 then
        skynet.call(room_fd, "lua", "in_line", user.uid)
    end
end



local jiesan_timer_id = nil
local jiesan_timer_time = 0
local in_line_flag = 0
local jiesan_fun = function()
    jiesan_timer_time = jiesan_timer_time + 1
    -- if user.uid == 2724 then
    -- print('===REQUEST.heartbeat======================================================================================================================jiesan_timer_time=======',user.uid,jiesan_timer_time)
    -- end
    if jiesan_timer_time > 6 then
        -- skynet.send(watch_dog, "lua", "close_agent", client_fd)
    end
end

function REQUEST.heartbeat(user, data)
    -- if user.uid == 2724 then
    --     print('===REQUEST.heartbeat=======11111111111111======================================================================================================================',json.encode(data))
    -- end
    time_out_stop_room_agent = 0
    if jiesan_timer_id then
        jiesan_timer_time = 0
    else
        jiesan_timer_id = add_skynet_timer2(10, jiesan_fun)
    end
    send_package(client_fd, { cmd = NetCmd.S2C_HEARTBEAT, uid = user.uid,ret=0 })
end

















function REQUEST.c2s_get_uid(user, data)
    local pack = { cmd = NetCmd.S2C_GET_UID, rs = 0, uid = data.uid }
    local query_sql = string.format("select * from user where uid = %d", data.uid)
    local rsss2 = skynet.call("MG_SAVE", "lua", "mysql_get_one", query_sql)
    if rsss2 == false then
        pack.msg = '用户不存在'
    else
        pack.rs = 1
        pack.head = rsss2.head
        pack.name = rsss2.name
    end
    send_package(client_fd, pack)
end





-- 房间发送过来的离开消息，若exit为true，则销毁
function POST.leave_room()
    room_id = nil
    room_fd = nil
    user:set_room_id(0);
end


-- 房间发送过来的离开消息，若exit为true，则销毁
function CMD.get_user_game(game_type, game_type2)
    local rs_arr = {}
    local uid = user.uid
    rs_arr.uid = user.uid
    rs_arr.card = user:get_gold()
    rs_arr.ju_num = 0
    rs_arr.win = 0
    rs_arr.ip = user:get_ip()
    if rs_arr.ip == '127.0.0.1' then
        rs_arr.ip = ''
    end
    local game = game_type2
    if game > 9999 and game_type < 9999 then
        game = game_type
    end
    local user_game = skynet.call("MG_SAVE", "lua", "redis_hget", 'user_game', math.ceil(uid) .. '_' .. math.ceil(game))
    if user_game ~= nil and user_game ~= false then
        user_game = json.decode(user_game)
        rs_arr.ju_num = user_game.num
        rs_arr.win = math.floor(user_game.win_num * 100 / user_game.num) .. '%'
    end
    -- print('==========rs_arr=======111============',uid,game,json.encode(user_game),json.encode(rs_arr))
    return rs_arr
end

function POST.send_user_data()
    -- 同步所有数据到客户端
    load_user(user, user.uid)
    send_package(client_fd,
        {
            cmd = NetCmd.S2C_SYNC_USER_DATA,
            key = 'gold',
            value = user:get_gold(),
        })
end




function CMD.update_user_bean(addr, bean)
    user.bean = math.floor(bean)
    -- print('=========update_user_info===========',bean,user.bean)
end


function CMD.reconnect(address, gate, fd)
    watch_dog = address
    gate_fd = gate
    client_fd = fd
    skynet.call(gate, "lua", "forward", fd)
    user.fd = client_fd

    -- 同步所有数据到客户端
    local raw_data = sync_schema(user)
    --dump_table(raw_data)
    if raw_data then
        send_package(client_fd, { cmd = NetCmd.S2C_LOAD_USER_DATA, db = raw_data,})
    end
end

function REQUEST.c2c_load_user_data(user, data)
    -- 同步所有数据到客户端
    local raw_data = sync_schema(user)
    --dump_table(raw_data)
    if raw_data then
        send_package(client_fd,
            { cmd = NetCmd.S2C_LOAD_USER_DATA,
                db = raw_data,
            })
    end
end

--发送短信
function REQUEST.c2s_phone_code(user, data)
    if data.phone_num ~= nil then
        local phone_num = string.format("%s",data.phone_num)
        local code = math.random(1000, 9999)
        local domain = 'ivqye.cn'
        local admin_domain = skynet.call('MG_SAVE','lua','get_admin_domain');
        if admin_domain['domain'] ~= nil then
            domain = admin_domain['domain']
        end
        local status, body = httpc.get(domain, '/admin/sendSmsCode?code=' .. code .. '&phone=' .. phone_num, {}, {})
        if  status == 200 and string.find(body,'smsId') ~= nil then
            local sql = string.format("insert into `ask_code` (id,phone_num,state,code,time) values (0,'%s',0,'%s',%d) ", data.phone_num, code, os.time())
            rs = skynet.call("MG_SAVE", "lua", "mysql_insert", sql)
            send_package(client_fd, { cmd = NetCmd.S2C_PHONE_CODE, ret = 0, })
        else
            send_package(client_fd, { cmd = NetCmd.S2C_PHONE_CODE, ret = 1, })
        end
    end
end

--绑定手机号
function REQUEST.c2s_phone_set(user, data)
    if data.phone_num ~= nil and data.code ~= nil then
        local query_sql = string.format("select * from ask_code where state=0 and phone_num='%s' and code='%s'",data.phone_num,data.code)
        local rs = skynet.call("MG_SAVE", "lua", "mysql_get_one",query_sql)
        if rs ~= nil and rs ~= false and rs.code == data.code then
            local query_sql = string.format("update `ask_code` set state=1 where id = %d ", rs.id)
            local rs = skynet.call("MG_SAVE", "lua", "update_sql",query_sql)

            local query_sql = string.format("update `user` set phone_num='%s' where uid = %d ", data.phone_num,user.uid)
            local rs = skynet.call("MG_SAVE", "lua", "update_sql",query_sql)
            send_package(client_fd, { cmd = NetCmd.S2C_PHONE_SET, ret = 0, })
            return
        end
    end
    send_package(client_fd, { cmd = NetCmd.S2C_PHONE_SET, ret = 1, })
end

function CMD.start(address, gate, fd, account, uid, login_roomid, data)
    skynet.error("-- agent -- CMD.start -------> address, gate, fd, account, uid, login_roomid, data:", address, gate, fd, account, uid, login_roomid, json.encode(data))
    watch_dog = address
    gate_fd = gate
    client_fd = fd
    skynet.call(gate, "lua", "forward", fd)

    user = skynet.call("MG_SAVE", "lua", "get_user_info",uid)
    user.uid = uid
    user.fd = client_fd

    local now = os.time()

    -- 同步所有数据到客户端
    if flag == nil then
        -- 设置登入时间
        local raw_data = clone(user)
        local room_id = 1
        local room_info = nil
        if room_id ~= nil and room_id > 0 then
            local hall_name = 'BJL_HALL'
            local fd, room_data = skynet.call(hall_name, "lua", "get_rooms", room_id)
            -- print('room_data============================================',json.encode(room_data))
            if fd == nil then
                data.room_id = 1
                id, fd = skynet.call(hall_name, "lua", "create_room", data)
                room_info = skynet.call(fd, "lua", "join", client_fd, uid, user.name, user.head, user.phone_num, user.money,user.score,user.no_say,user.ai,user.tourist)
            else
                room_info = skynet.call(fd, "lua", "join", client_fd, uid, user.name, user.head, user.phone_num, user.money,user.score,user.no_say,user.ai,user.tourist)
            end
            room_fd = fd
        end
        raw_data.room_id = login_roomid
        -- if raw_data then
        --     send_package(client_fd,
        --     { cmd = NetCmd.S2C_LOAD_USER_DATA,
        --     db = raw_data,
        --     })
        -- end
        if login_roomid > 0 then
            REQUEST.join_room_again(user, { room_id = login_roomid })
        end


        local time_out_stop_room_fun_agent = function()       -- 定时器触发
        time_out_stop_room_agent = time_out_stop_room_agent + 1
        if time_out_stop_room_agent >= 60 then --3600 秒后 没动作，自动解散房间
        destory()
        end
        end
        add_skynet_timer2(100, time_out_stop_room_fun_agent)
    end
end

---------------------------------------- skynet.start ----------------------------------------
skynet.start(function()
    httpc.dns() -- set dns server
    skynet.dispatch("lua", function(_, address, command, ...)
        local f = CMD[command]
        if f then
            -- skynet.error("-- agent ------->  do CMD." .. command)
            skynet.ret(skynet.pack(f(address, ...)))
            return
        end

        f = POST[command]
        if f then
            -- skynet.error("-- agent ------->  do POST." .. command)
            f(...)
        end
    end)
end)

skynet.register_protocol {
    name = "client",
    id = skynet.PTYPE_CLIENT,
    pack = function(text)
        return text, #text
    end,
    unpack = function(msg, sz)
        return skynet.tostring(msg, sz)
    end,
    dispatch = function(_, _, text, ...)
        local json_data = unpack_package(text)
        if not json_data then
            return
        end
        local f = REQUEST.func_map[json_data.cmd]
        if not f then
            if room_fd and room_fd > 0 then     -- 若已经进入了房间，则直接转发到房间
            skynet.send(room_fd, "client", text)
            end
            return
        end

        if json_data.cmd ~= 5 then
            skynet.error("-- agent ------->  do REQUEST.", json_data.cmd, text)
        end
        --f(user,json_data)
        make_queue(user, json_data, f)
    end
}



function REQUEST.web_error(fd, data)
    local text = json.encode(data)
    packdeal.writelog_error('error', text)
end

function REQUEST.c2s_all_room_jiesan()
    local all_rooms = skynet.call("MG_SAVE", "lua", "get_all_rooms")
    for room_id, hall_name in pairs(all_rooms) do
        -- print('hall_name=======',room_id,hall_name)
        local room_fd = skynet.call(hall_name, "lua", "get_rooms", room_id)
        if room_fd ~= nil then
            skynet.send(room_fd, "lua", "jiesan")
        end
    end
    local packet = { cmd = NetCmd.S2C_MJ_JOIN_ROOM, ok = 1 }
    send_package(client_fd, packet)
end

function CMD.web_is_uid_fid(address, data)
    local uid = math.floor(user.uid)
    local name = user:get_name()
    local fid = math.floor(data)
    return FRIENDS.is_uid_fid(uid, fid)
end

function CMD.web_friends_add(address, data)
    local uid = math.floor(user.uid)
    local name = user:get_name()
    local fid = math.floor(data)
    local rs = FRIENDS.friends_add(uid, fid)

    if rs > 0 then
        local fid_arr = FRIENDS.get_fid_admin(fid)
        local mail_to_uid = 0
        if fid_arr ~= false or str ~= nil then
            for k, v in pairs(fid_arr) do
                mail_to_uid = v.uid
                fname = v.name
                local mails = { 0, 1, mail_to_uid, 3, 0, '玩家' .. name .. ' ID ' .. uid .. ' 申请加入俱乐部' .. fname .. ' ID ' .. fid, '玩家' .. name .. ' ID ' .. uid .. ' 申请加入俱乐部' .. fname .. ' ID ' .. fid,
                    os.time(), '{\\"uid\\":' .. uid .. ',\\"fid\\":' .. fid .. '}' }
                MAIL.save_mails(mails)
            end
        end
        return 1
    else
        return 2
    end

end












-- 大厅路由
function forward_hall(func, hall_name)
    return function(user, data)
        return func(user, data, hall_name)
    end
end


REQUEST.func_map = {
    [NetCmd.C2S_HEARTBEAT]            = function (user,data)
        send_package(client_fd, {cmd=NetCmd.S2C_HEARTBEAT, sign=1})
    end,

    [ NetCmd.C2S_PHONE_CODE ]       = REQUEST.c2s_phone_code,
    [ NetCmd.C2S_PHONE_SET ]       = REQUEST.c2s_phone_set,

}